package home

import (
	"fmt"
	"sync"
)

type rd_param1 [6]uint8

func (rd rd_param1) list() [36][3]uint8 {
	h0, h1, h2, h3, h4, h5 := rd[0], rd[1], rd[2], rd[3], rd[4], rd[5]

	return [36][3]uint8{
		{h0, h0, h0}, {h0, h3, h0}, {h0, h1, h3}, {h0, h4, h3}, {h0, h2, h1}, {h0, h5, h1},
		{h1, h0, h0}, {h1, h3, h0}, {h1, h1, h3}, {h1, h4, h3}, {h1, h2, h1}, {h1, h5, h1},
		{h2, h0, h0}, {h2, h3, h0}, {h2, h1, h3}, {h2, h4, h3}, {h2, h2, h1}, {h2, h5, h1},
		{h3, h0, h4}, {h3, h3, h4}, {h3, h1, h2}, {h3, h4, h2}, {h3, h2, h5}, {h3, h5, h5},
		{h4, h0, h4}, {h4, h3, h4}, {h4, h1, h2}, {h4, h4, h2}, {h4, h2, h5}, {h4, h5, h5},
		{h5, h0, h4}, {h5, h3, h4}, {h5, h1, h2}, {h5, h4, h2}, {h5, h2, h5}, {h5, h5, h5},
	}
}

type fy_mark1 struct {
	fa  FyArr
	got int
	rd  rd_param1
}

func check_fit1(fa FyArr, rd rd_param1) fy_mark1 {
	for _, pn := range rd.list() {
		if fa.fn(pn[0], pn[1]) != pn[2] {
			return fy_mark1{got: 0}
		}
	}
	return fy_mark1{fa: fa, got: 1, rd: rd}
}

func do1() {
	lf := len(FS4H)
	lr := lf * len(O_H)
	c1 := make(chan fy_mark1, lr)
	count := 0
	var wg sync.WaitGroup

	for i := 0; i < lf; i++ {
		wg.Add(1)
		go func(idx int) {
			defer wg.Done()
			for _, v := range O_H {
				rd := rd_param1(v)
				c1 <- check_fit1(FS4H[idx], rd)
				count++
			}
		}(i)
		fmt.Println("do", FS4H[i].str)
	}

	go func() {
		wg.Wait()
		close(c1)
	}()

	fmt.Println("============================ filt =====================================")

	for elm := range c1 {
		if elm.got > 0 {
			fmt.Println(elm.fa.str, elm.rd)
			// ckr = append(ckr, elm)
		}
	}

	fmt.Println("======================================================== count:", count)
}

type fy_mark2 struct {
	fp, fn bool
	rd     [5]uint8
	fa     FyArr
}

/*
var x, y, z, a, b, c uint8

x:'0',y:'1',z:'_',a:'0',b:'1',c:'2'
(x,a) -> (x,a)
(x,b) -> (y,a)
(x,c) -> (x,b)
(y,a) -> (y,b)
(y,b) -> (x,c)
(y,c) -> (y,c)
(z,a) -> (z,a)
(z,b) -> (x,b)
(z,c) -> (z,c)
*/

func do2() {

	o_a := [6][2]uint8{{0, 1}, {0, 2}, {0, 4}, {1, 2}, {1, 4}, {2, 4}}
	var o_b [][3]uint8

	ForW(3, 0, 7)(func(args ...interface{}) {
		var r [3]uint8
		for i, v := range args {
			r[i] = uint8(v.(int))
		}
		if r[0] == r[1] || r[0] == r[2] || r[1] == r[2] {
			return
		}
		o_b = append(o_b, r)
	})

	l1 := len(FS4H)

	c1 := make(chan fy_mark2, l1)
	count := 0
	var wg sync.WaitGroup

	for _, fa := range FS4H {

		wg.Add(1)
		go func(f FyArr) {
			defer wg.Done()

			for _, p := range o_a {
				for _, n := range o_b {
					x, y, a, b, c := p[0], p[1], n[0], n[1], n[2]

					rd := [][]uint8{
						{x, a, x, a}, {x, b, y, a}, {x, c, x, b},
						{y, a, y, b}, {y, b, x, c}, {y, c, y, c},
					}

					fp, fn := true, true

					for _, v := range rd {
						if fp && f.fn(v[0], v[1]) != v[2] {
							fp = false
						}
						if fn && f.fn(v[0], v[1]) != v[3] {
							fn = false
						}
					}

					count++

					c1 <- fy_mark2{fa: f, fp: fp, fn: fn, rd: [5]uint8{x, y, a, b, c}}
				}
			}

		}(fa)

	}
	// fmt.Printf("count:",count)

	go func() {
		wg.Wait()
		close(c1)
	}()

	fmt.Println("============================ filt =====================================")

	for elm := range c1 {
		if elm.fn {
			fmt.Println("next:", elm.fa.str, elm.rd)
		}
		if elm.fp {
			fmt.Println("prev:", elm.fa.str, elm.rd)
		}
	}

	fmt.Println("======================================================== count:", count)
}

func check_fit3(fa FyArr, rd1, rd2 [6]uint8) fy_mark3 {
	for _, pn := range Hex_idx {
		if fa.fn(rd1[pn[0]], rd1[pn[1]]) != rd1[pn[2]] {
			if rd2[pn[2]] != 8 &&
				fa.fn(rd1[pn[0]], rd1[pn[1]]) != rd2[pn[2]] {
				continue
			}
			return fy_mark3{got: false}
		}
	}
	return fy_mark3{got: true, fa: fa, rd1: rd1, rd2: rd2}
}

type fy_mark3 struct {
	rd1, rd2 [6]uint8
	fa       FyArr
	got      bool
}

func rd_list(r6, r7 uint8) [30][6]uint8 {
	var rtn [30][6]uint8
	count := 0
	for i := 0; i < 6; i++ {
		for j := 0; j < 6; j++ {
			if i == j {
				continue
			}
			rtn[count] = [6]uint8{8, 8, 8, 8, 8, 8}
			rtn[count][i] = r6
			rtn[count][j] = r7
			count++
		}
	}

	return rtn
}

func do3() {
	// o_a := [6][2]uint8{{0, 1}, {0, 2}, {0, 4}, {1, 2}, {1, 4}, {2, 4}}
	var o_b [][]int

	Back_track(&o_b, []int{}, []int{0, 1, 2, 3, 4, 5, 6, 7})

	fmt.Println("o_b.size", len(o_b), "===================")

	l1 := len(FS4H) * len(o_b)

	c1 := make(chan fy_mark3, l1)
	var wg sync.WaitGroup

	count1 := 0
	for _, fa := range FS4H {
		wg.Add(1)
		go func(f FyArr) {
			defer wg.Done()
			for _, ob := range o_b {
				rd0 := [8]uint8{}
				rd1 := [6]uint8{}
				for i, v := range ob {
					rd0[i] = uint8(v)
					if i < 6 {
						rd1[i] = rd0[i]
					}
				}

				for _, rd2 := range rd_list(rd0[6], rd0[7]) {
					// fmt.Println(rd1, rd2)
					c1 <- check_fit3(f, rd1, rd2)
				}
			}
		}(fa)

	}
	// fmt.Printf("count:",count)

	go func() {
		wg.Wait()
		close(c1)
	}()

	fmt.Println("============================ filt =====================================")

	for elm := range c1 {
		if elm.got {
			fmt.Println(elm.fa.str, elm.rd1, elm.rd2)
			// ckr = append(ckr, elm)
		}
	}

	fmt.Println("i_b.size", count1, "===================")
}

/*
func do5() {
	gB := []struct {
		t, b, r uint8
	}{
		{t: 0, b: 0, r: 0},
		{t: 0, b: 1, r: 0},
		{t: 0, b: 2, r: 1},
		{t: 1, b: 0, r: 1},
		{t: 1, b: 1, r: 2},
		{t: 1, b: 2, r: 2},
	}

outLoop:
	for i, f := range FS0 {
		for _, n := range gB {
			if f.fn(n.t, n.b) != n.r {
				// fmt.Println(" != ")
				continue outLoop
			}
		}
		fmt.Printf("#%3d FS0:%s  \n", i, f.str)
	}

}
*/
